﻿using System;
using System.Collections;
using System.Data;
using System.Web.UI.WebControls;

namespace MCSFramework.Common
{
    public class MatrixTable
    {
        #region 将DataTable矩阵化
        /// <summary>
        /// 将DataTable矩阵化
        /// </summary>
        /// <param name="SourceTable">源表</param>
        /// <param name="RowGroup">行组,矩阵化后为目的表的主键</param>
        /// <param name="ColumnGroup">列组,矩阵化后根据列组数据自动生成列</param>
        /// <param name="ValueGroup">值组,矩阵化后自动将值累加到数据区中</param>
        /// <param name="AddRowSummary">是否在最后一行加入合计行</param>
        /// <param name="AddColumnSummary">是否在最后一列中加入合计列</param>
        /// <returns></returns>
        public static DataTable Matrix(DataTable SourceTable, string[] RowGroup, string[] ColumnGroup, string[] ValueGroup, bool AddRowSummary, bool AddColumnSummary)
        {
            if (SourceTable.Rows.Count == 0) return SourceTable;
            DataTable DestTable = new DataTable();
            Hashtable hs_summary = new Hashtable();

            #region 给目的表加行组键
            DataColumn[] pkc = new DataColumn[RowGroup.Length];
            string sort = "";
            for (int i = 0; i < RowGroup.Length; i++)
            {
                DataColumn dc = new DataColumn(RowGroup[i], SourceTable.Columns[RowGroup[i]].DataType);
                DestTable.Columns.Add(dc);
                pkc[i] = dc;
                sort += RowGroup[i] + ",";
            }
            DestTable.PrimaryKey = pkc;
            sort = sort.Substring(0, sort.Length - 1);
            SourceTable.DefaultView.Sort = sort;

            //获取列组的唯一值,根据数据决定有哪些列
            ArrayList list = new ArrayList();
            if (ColumnGroup.Length == 0)
            {
                list.Add("");
            }
            else
            {
                foreach (DataRow dr in SourceTable.Rows)
                {
                    string v = "";
                    foreach (string dc in ColumnGroup)
                    {
                        v += (dr[dc].ToString().Trim() == string.Empty ? "NULL" : dr[dc].ToString().Trim()) + "→";
                    }
                    if (ColumnGroup.Length > 0) v = v.Substring(0, v.Length - 1);
                    if (!list.Contains(v)) list.Add(v);

                }
                list.Sort();        //列排序
            }

            //扩展目的表的列
            ArrayList al_datacolumns = new ArrayList();        //目的Table含有的数据列
            for (int i = 0; i < list.Count; i++)
            {
                foreach (string dc in ValueGroup)
                {
                    string columnname = "";

                    if (ColumnGroup.Length == 0)
                    {
                        columnname = dc;
                    }
                    else
                    {
                        if (ValueGroup.Length == 1)
                            columnname = list[i].ToString();
                        else
                            columnname = list[i] + "→" + dc;
                    }


                    DestTable.Columns.Add(columnname, SourceTable.Columns[dc].DataType).DefaultValue = 0;
                    al_datacolumns.Add(columnname);

                    decimal _d = 0;
                    hs_summary.Add(columnname, _d);
                }
            }
            #endregion

            #region 加入合计列
            if (AddColumnSummary && ColumnGroup.Length > 0)
            {
                foreach (string dv in ValueGroup)
                {
                    string expression = "";

                    for (int i = 0; i < list.Count; i++)
                    {
                        if (ValueGroup.Length == 1)
                            expression += "[" + list[i] + "] +";
                        else
                            expression += "[" + list[i] + "→" + dv + "] +";
                    }
                    expression = expression.Substring(0, expression.Length - 1);

                    if (ValueGroup.Length == 1)
                    {
                        DestTable.Columns.Add("合计", SourceTable.Columns[dv].DataType, expression);
                        al_datacolumns.Add("合计");
                    }
                    else
                    {
                        DestTable.Columns.Add("合计→" + dv, SourceTable.Columns[dv].DataType, expression);
                        al_datacolumns.Add("合计→" + dv);
                    }
                }
            }
            #endregion

            #region 增加数据
            Hashtable hs_prerowvalue = new Hashtable();
            foreach (DataRowView dr in SourceTable.DefaultView)
            {
                //判断是否已存在相同键值的行
                object[] pk = new object[RowGroup.Length];
                for (int i = 0; i < RowGroup.Length; i++)
                {
                    pk[i] = dr[RowGroup[i]];
                }
                if (!DestTable.Rows.Contains(pk))
                {
                    #region 新增该数据行
                    DataRow newrow = DestTable.NewRow();
                    foreach (string dc in RowGroup)
                    {
                        newrow[dc] = dr[dc];
                    }

                    string columnname_pre = "", columnname_fullname = "";
                    if (ColumnGroup.Length > 0)
                    {
                        foreach (string dc in ColumnGroup)
                        {
                            columnname_pre += (dr[dc].ToString().Trim() == string.Empty ? "NULL" : dr[dc].ToString().Trim()) + "→";
                        }
                        columnname_pre = columnname_pre.Substring(0, columnname_pre.Length - 1);
                    }


                    foreach (string dv in ValueGroup)
                    {
                        if (ColumnGroup.Length == 0)
                            columnname_fullname = dv;
                        else
                        {
                            if (ValueGroup.Length == 1)
                                columnname_fullname = columnname_pre;
                            else
                                columnname_fullname = columnname_pre + "→" + dv;
                        }
                        decimal v = 0;
                        try
                        {
                            if (dr[dv].ToString() != "")
                                v = decimal.Parse(dr[dv].ToString());
                        }
                        catch { }
                        newrow[columnname_fullname] = v;

                        hs_summary[columnname_fullname] = (decimal)hs_summary[columnname_fullname] + v;
                    }
                    DestTable.Rows.Add(newrow);
                    #endregion
                }
                else
                {
                    //存在，累加行
                    DataRow row = DestTable.Rows.Find(pk);

                    string columnname_pre = "", columnname_fullname = "";
                    if (ColumnGroup.Length > 0)
                    {
                        foreach (string dc in ColumnGroup)
                        {
                            columnname_pre += (dr[dc].ToString().Trim() == string.Empty ? "NULL" : dr[dc].ToString().Trim()) + "→";
                        }
                        columnname_pre = columnname_pre.Substring(0, columnname_pre.Length - 1);
                    }


                    foreach (string dv in ValueGroup)
                    {
                        if (ColumnGroup.Length == 0)
                            columnname_fullname = dv;
                        else
                        {
                            if (ValueGroup.Length == 1)
                                columnname_fullname = columnname_pre;
                            else
                                columnname_fullname = columnname_pre + "→" + dv;
                        }
                        decimal v = 0;

                        try
                        {
                            if (dr[dv].ToString() != "")
                                v = decimal.Parse(dr[dv].ToString());
                        }
                        catch { }

                        if (row[columnname_fullname].ToString() != "")
                            row[columnname_fullname] = decimal.Parse(row[columnname_fullname].ToString()) + v;
                        else
                            row[columnname_fullname] = v;

                        //合计累加
                        hs_summary[columnname_fullname] = (decimal)hs_summary[columnname_fullname] + v;
                    }
                }
            }
            #endregion

            #region 增加合计行
            if (AddRowSummary)
            {
                DataRow summaryrow = DestTable.NewRow();
                foreach (DataColumn column in DestTable.Columns)
                {
                    if (column.DataType.FullName == "System.String")
                    {
                        summaryrow[column] = "总计";
                        break;
                    }
                }

                bool _b = false;
                foreach (DataColumn pk in pkc)
                {
                    //因为主键不能为空，所以必须设置值
                    switch (pk.DataType.ToString())
                    {
                        case "System.String":
                            if (!_b)
                            {
                                summaryrow[pk] = "总计";
                                _b = true;
                            }
                            else
                                summaryrow[pk] = "";
                            break;
                        case "System.Decimal":
                        case "System.Int16":
                        case "System.Int32":
                        case "System.Int64":
                            summaryrow[pk] = 0;
                            break;
                        case "System.DateTime":
                            summaryrow[pk] = DateTime.Today;
                            break;
                    }
                }
                foreach (object columnname in hs_summary.Keys)
                {
                    summaryrow[columnname.ToString()] = hs_summary[columnname.ToString()];
                }

                DestTable.Rows.Add(summaryrow);
            }
            #endregion

            return DestTable;
        }

        #region 方法重载
        /// <summary>
        /// 将DataTable矩阵化
        /// </summary>
        /// <param name="SourceTable">源表</param>
        /// <param name="RowGroup">行组,矩阵化后为目的表的主键</param>
        /// <param name="ColumnGroup">列组,矩阵化后根据列组数据自动生成列</param>
        /// <param name="ValueGroup">值组,矩阵化后自动将值累加到数据区中</param>
        /// <returns></returns>
        public static DataTable Matrix(DataTable SourceTable, string[] RowGroup, string[] ColumnGroup, string[] ValueGroup)
        {
            return Matrix(SourceTable, RowGroup, ColumnGroup, ValueGroup, true, true);
        }

        /// <summary>
        /// 将DataTable矩阵化
        /// </summary>
        /// <param name="SourceTable">源表</param>
        /// <param name="RowGroup">行组,矩阵化后为目的表的主键</param>
        /// <param name="ColumnGroup">列组,矩阵化后根据列组数据自动生成列</param>
        /// <param name="ValueGroup">值列,矩阵化后自动将值累加到数据区中</param>
        /// <param name="AddRowSummary">是否在最后一行加入合计行</param>
        /// <param name="AddColumnSummary">是否在最后一列中加入合计列</param>
        /// <returns></returns>
        public static DataTable Matrix(DataTable SourceTable, string[] RowGroup, string[] ColumnGroup, string ValueGroup, bool AddRowSummary, bool AddColumnSummary)
        {
            string[] ValueGroups = { ValueGroup };
            return Matrix(SourceTable, RowGroup, ColumnGroup, ValueGroups, AddRowSummary, AddColumnSummary);
        }


        /// <summary>
        /// 将DataTable矩阵化
        /// </summary>
        /// <param name="SourceTable">源表</param>
        /// <param name="RowGroup">行组,矩阵化后为目的表的主键</param>
        /// <param name="ColumnGroup">列组,矩阵化后根据列数据自动生成列</param>
        /// <param name="ValueGroup">值列,矩阵化后自动将值累加到数据区中</param>
        /// <param name="AddRowSummary">是否在最后一行加入合计行</param>
        /// <param name="AddColumnSummary">是否在最后一列中加入合计列</param>
        /// <returns></returns>
        public static DataTable Matrix(DataTable SourceTable, string[] RowGroup, string[] ColumnGroup, string ValueGroup)
        {
            string[] ValueGroups = { ValueGroup };
            return Matrix(SourceTable, RowGroup, ColumnGroup, ValueGroups, true, true);
        }

        /// <summary>
        /// 将DataTable矩阵化
        /// </summary>
        /// <param name="SourceTable">源表</param>
        /// <param name="RowGroup">行组,矩阵化后为目的表的主键</param>
        /// <param name="ColumnGroup">列,矩阵化后根据列数据自动生成列</param>
        /// <param name="ValueGroup">值,矩阵化后自动将值累加到数据区中</param>
        /// <param name="AddRowSummary">是否在最后一行加入合计行</param>
        /// <param name="AddColumnSummary">是否在最后一列中加入合计列</param>
        /// <returns></returns>
        public static DataTable Matrix(DataTable SourceTable, string[] RowGroup, string ColumnGroup, string ValueGroup, bool AddRowSummary, bool AddColumnSummary)
        {
            string[] ColumnGroups = { ColumnGroup };
            string[] ValueGroups = { ValueGroup };

            return Matrix(SourceTable, RowGroup, ColumnGroups, ValueGroups, AddRowSummary, AddColumnSummary);
        }

        /// <summary>
        /// 将DataTable矩阵化
        /// </summary>
        /// <param name="SourceTable">源表</param>
        /// <param name="RowGroup">行组,矩阵化后为目的表的主键</param>
        /// <param name="ColumnGroup">列,矩阵化后根据列数据自动生成列</param>
        /// <param name="ValueGroup">值,矩阵化后自动将值累加到数据区中</param>
        /// <returns></returns>
        public static DataTable Matrix(DataTable SourceTable, string[] RowGroup, string ColumnGroup, string ValueGroup)
        {
            string[] ColumnGroups = { ColumnGroup };
            string[] ValueGroups = { ValueGroup };

            return Matrix(SourceTable, RowGroup, ColumnGroups, ValueGroups, true, true);
        }
        #endregion
        #endregion

        #region 调整GridView控件的表头显示格式
        /// <summary>
        /// 将指定的GridView的列标题行矩阵化,配合MatrixTable使用
        /// </summary>
        /// <param name="gv"></param>
        public static void GridViewMatric(GridView gv)
        {
            GridViewRow row = gv.HeaderRow;//获取标题行
            if (row == null) return;
            if (row.Cells.Count == 0) return;

            #region 将列中分隔符转为多行表头            
            //group表示拆分后标题有多少行
            int groups = 1;
            foreach (TableCell c in row.Cells)
            {
                groups = c.Text.Split('→').Length;
                if (groups > 1) break;//存在一个→符号则立刻退出
            }
            if (groups == 1) return;//不存在分割符号

            string[] columnname = new string[row.Cells.Count];
            for (int i = 0; i < columnname.Length; i++)
            {
                if (row.Cells[i].Visible)
                    columnname[i] = row.Cells[i].Text;
                else
                    columnname[i] = "";

                if (columnname[i] == "" && gv.Columns.Count > i)//gv列数与gv的表头cell的数目可以不等，此处判断gv的表头数目少于等于gv的列数，即表头有且只有一行吗，无自定义表头样式
                {
                    columnname[i] = gv.Columns[i].HeaderText;
                }
            }

            TableCellCollection dtc = row.Cells;
            dtc.Clear();

            for (int gi = 0; gi <= groups - 1; gi++)//对最终拆分的行数遍历，第一次取出标题头，之后每次取出子标题
            {
                string groupname = "";
                for (int i = 0; i < columnname.Length; i++)
                {

                    string s = columnname[i];
                    if (s.IndexOf('→') == -1)//不存在→符号
                    {
                        if (s != "")
                        {
                            TableHeaderCell c = new TableHeaderCell();
                            c.Text = s;
                            c.RowSpan = groups - gi;
                            dtc.Add(c);
                            columnname[i] = "";
                        }
                    }
                    else
                    {
                        if (s.Substring(0, s.IndexOf('→')) != groupname)
                        {
                            TableHeaderCell c = new TableHeaderCell();
                            c.Text = s.Substring(0, s.IndexOf('→'));

                            dtc.Add(c);

                            groupname = s.Substring(0, s.IndexOf('→'));
                            columnname[i] = s.Substring(s.IndexOf('→') + 1);
                        }
                        else
                        {
                            if (dtc[dtc.Count - 1].ColumnSpan == 0) dtc[dtc.Count - 1].ColumnSpan = 1;//当未指定cell的ColumnSpan属性时，该值为0
                            dtc[dtc.Count - 1].ColumnSpan += 1;
                            columnname[i] = s.Substring(s.IndexOf('→') + 1);
                        }
                    }
                }
                if (gi != groups - 1)
                    dtc[dtc.Count - 1].Text += "</th></tr><tr>";
            }
            #endregion
            
        }

        public static void GridViewMergSampeValueRow(GridView gv, int ColumnIndex)
        {
            GridViewMergSampeValueRow(gv, ColumnIndex, "", 0, "");
        }
        /// <summary>
        /// 将指定的GridView中指定列中相邻行相同值的单元格合并显示
        /// </summary>
        /// <param name="gv"></param>
        /// <param name="ColumnIndex">合并显示的列序</param>
        public static void GridViewMergSampeValueRow(GridView gv, int ColumnIndex, string BackColor, int BorderWidth, string BorderColor)
        {
            if (gv.Rows.Count == 0) return;
            #region 合并行组中相邻行相同值
            int rowspan = 1;
            for (int i = gv.Rows.Count - 1; i > 0; i--)
            {
                if (BackColor != "")
                    gv.Rows[i].Cells[ColumnIndex].Style.Add("background-color", BackColor);
                else
                    gv.Rows[i].Cells[ColumnIndex].Style.Add("background-color", "#ffffff");

                if (ColumnIsSampe(gv, i, ColumnIndex))
                {
                    gv.Rows[i].Cells[ColumnIndex].Visible = false;
                    rowspan++;
                }
                else
                {
                    gv.Rows[i].Cells[ColumnIndex].RowSpan = rowspan;

                    if (BorderWidth > 0)
                    {
                        gv.Rows[i].Cells[ColumnIndex].Style.Add("border-top-style", "solid");
                        gv.Rows[i].Cells[ColumnIndex].Style.Add("border-top-width", BorderWidth.ToString() + "px");
                        if (BorderColor != "") gv.Rows[i].Cells[ColumnIndex].Style.Add("border-color", BorderColor);
                    }
                    rowspan = 1;
                }
            }
            gv.Rows[0].Cells[ColumnIndex].RowSpan = rowspan;

            if (BackColor != "")
                gv.Rows[0].Cells[ColumnIndex].Style.Add("background-color", BackColor);
            else
                gv.Rows[0].Cells[ColumnIndex].Style.Add("background-color", "#ffffff");

            if (BorderWidth > 0)
            {
                gv.Rows[0].Cells[ColumnIndex].Style.Add("border-top-style", "solid");
                gv.Rows[0].Cells[ColumnIndex].Style.Add("border-top-width", BorderWidth.ToString() + "px");
                if (BorderColor != "") gv.Rows[0].Cells[ColumnIndex].Style.Add("border-color", BorderColor);
            }
            #endregion
        }

        /// <summary>
        /// 判断指定行与列之前的单元格Text值是否一致，全部相同返回true，存在不同值返回false
        /// </summary>
        /// <param name="gv"></param>
        /// <param name="row"></param>
        /// <param name="column"></param>
        /// <returns></returns>
        private static bool ColumnIsSampe(GridView gv, int row, int column)
        {
            if (gv.Rows[row].Cells[column].Text.Trim() == "&nbsp;"||gv.Rows[row].Cells[column].Text.Trim() == "") return false;
            for (int i = column; i >= 0; i--)
            {
                if (gv.Rows[row].Cells[i].Text != gv.Rows[row - 1].Cells[i].Text) return false;//此处用return，即第一次循环结束满足条件立即退出
            }

            return true;
        }
        #endregion

        #region 行小计处理相关
        /// <summary>
        /// 在DataTable中增加小计行
        /// </summary>
        /// <param name="SourceDT">源DataTable</param>
        /// <param name="Columns">待小计的列（名称）数组</param>
        /// <param name="Values">待小计的值列（名称）数组</param>
        /// <param name="CalSumValue">是否求行总计</param>
        public static void TableAddRowSubTotal(DataTable SourceDT, string[] Columns, string[] Values, bool CalSumValue)
        {
            if (Columns.Length > 0 && Values.Length > 0 && SourceDT != null && SourceDT.Rows.Count > 0)
            {
                Hashtable _ht = new Hashtable();
                CalSum(SourceDT, Values, ref _ht);

                //每个待小计的列
                foreach (string column in Columns)
                {
                    //当前列索引
                    int columnindex = 0;
                    while (columnindex < SourceDT.Columns.Count)
                    {
                        if (SourceDT.Columns[columnindex].ColumnName == column)
                            break;
                        else
                            columnindex++;
                    }

                    int BeginPosition = -1;
                    int EndPosition = -1;

                    //遍历每个数据行
                    for (int i = 1; i < SourceDT.Rows.Count; i++)
                    {
                        //如果行和上一行的值不匹配
                        if (!IsSame(SourceDT, columnindex, i))
                        {
                            BeginPosition = GetBeginPosition(SourceDT, columnindex, i);
                            EndPosition = i - 1;

                            AddNewRow(ref SourceDT, columnindex, BeginPosition, EndPosition, Values);

                        }
                        else if (i == SourceDT.Rows.Count - 1 && !RowContainSummary(SourceDT, columnindex, i))
                        {
                            BeginPosition = GetBeginPosition(SourceDT, columnindex, i);
                            EndPosition = i;
                            AddNewRow(ref SourceDT, columnindex, BeginPosition, EndPosition, Values);
                            break;
                        }
                        else
                            continue;
                    }
                }

                //如果要添加总计行
                if (CalSumValue)
                {
                    AddSumRow(ref SourceDT, Columns, Values, _ht);
                }
            }
        }

        /// <summary>
        /// 判断某行是否和上一行相同
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="ColumnIndex"></param>
        /// <param name="CurrentInex"></param>
        /// <returns></returns>
        private static bool IsSame(DataTable dt, int ColumnIndex, int CurrentInex)
        {
            string Flag = "Y";
            for (int i = 0; i <= ColumnIndex; i++)
            {
                if (!RowContainSummary(dt, ColumnIndex, CurrentInex - 1) && (dt.Rows[CurrentInex][i].ToString() != dt.Rows[CurrentInex - 1][i].ToString()))
                {
                    Flag = "N";
                    break;
                }
            }
            return Flag == "Y";
        }

        /// <summary>
        /// 获取第一次匹配特定行的位置
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="ColumnIndex"></param>
        /// <param name="CurrentInex"></param>
        /// <returns></returns>
        private static int GetBeginPosition(DataTable dt, int ColumnIndex, int CurrentInex)
        {
            int BeginPosition = 0;
            for (int i = CurrentInex - 1; i >= 0; i--)
            {
                if (RowContainSummary(dt, ColumnIndex, i))
                {
                    BeginPosition = i + 1;
                    break;
                }
                else
                {
                    continue;
                }
            }
            return BeginPosition;
        }

        /// <summary>
        /// 添加一个小计行
        /// </summary>
        /// <param name="SourceDT"></param>
        /// <param name="ColumnIndex"></param>
        /// <param name="BeginPosition"></param>
        /// <param name="EndPosition"></param>
        /// <param name="Values"></param>
        private static void AddNewRow(ref DataTable SourceDT, int ColumnIndex, int BeginPosition, int EndPosition, string[] Values)
        {
            SourceDT.BeginLoadData();
            DataRow dr_newrow = SourceDT.NewRow();
            //插入该列前面的列值
            for (int k = 0; k <= ColumnIndex; k++)
            {
                dr_newrow[k] = SourceDT.Rows[EndPosition][k];
            }
            dr_newrow[ColumnIndex + 1] = "小计";

            //插入该列后面列值
            for (int k = ColumnIndex + 2; k < SourceDT.Columns.Count; k++)
            {
                string flag_isvalue = "N";
                foreach (string s in Values)
                {
                    if (s == SourceDT.Columns[k].ColumnName)
                    {
                        flag_isvalue = "Y";
                        break;
                    }
                }
                if (flag_isvalue == "Y")//为小计列
                {
                    decimal sumvalue = 0;
                    for (int m = BeginPosition; m <= EndPosition; m++)
                    {
                        try
                        {
                            sumvalue += decimal.Parse(SourceDT.Rows[m][SourceDT.Columns[k].ColumnName].ToString());
                        }
                        catch { continue; }
                    }
                    dr_newrow[SourceDT.Columns[k].ColumnName] = sumvalue;
                }
            }
            SourceDT.Rows.InsertAt(dr_newrow, EndPosition + 1);
        }

        /// <summary>
        /// 判断某行是否为小计产生的
        /// </summary>
        /// <param name="SourceDT"></param>
        /// <param name="ColumnIndex"></param>
        /// <param name="RowIndex"></param>
        /// <returns></returns>
        private static bool RowContainSummary(DataTable SourceDT, int ColumnIndex, int RowIndex)
        {
            string Flag = "N";
            for (int i = 0; i <= ColumnIndex + 1; i++)
            {
                if (SourceDT.Rows[RowIndex][i].ToString().IndexOf("计") > -1)
                {
                    Flag = "Y";
                    break;
                }
            }
            return Flag == "Y";

        }

        /// <summary>
        ///处理前获取总计 
        /// </summary>
        /// <param name="SourceDT"></param>
        /// <param name="cols"></param>
        /// <param name="values"></param>
        private static void CalSum(DataTable SourceDT, string[] values, ref Hashtable _ht)
        {
            foreach (string value in values)
            {
                _ht.Add(value, 0);
                foreach (DataRow dr in SourceDT.Rows)
                {
                    try
                    {
                        _ht[value] = decimal.Parse(_ht[value].ToString()) + decimal.Parse(dr[value].ToString());
                    }
                    catch { }
                }
            }
        }

        /// <summary>
        /// 在最后添加总计行
        /// </summary>
        /// <param name="SourceDT"></param>
        /// <param name="cols"></param>
        /// <param name="values"></param>
        /// <param name="_ht"></param>
        private static void AddSumRow(ref DataTable SourceDT, string[] cols, string[] values, Hashtable _ht)
        {
            DataRow dr_sum = SourceDT.NewRow();
            foreach (DataColumn column in SourceDT.Columns)
            {
                if (column.DataType.FullName == "System.String")
                {
                    dr_sum[column] = "";

                }
            }
            dr_sum[cols[0]] = "总计";

            foreach (string value in values)
            {
                dr_sum[value] = _ht[value];
            }
            SourceDT.Rows.Add(dr_sum);
        }

        /// <summary>
        /// 针对矩阵化后的DataTable，增加行组小计
        /// </summary>
        /// <param name="SourceDT">源数据表</param>
        /// <param name="rowgroup">要加上小计的行组</param>
        /// <param name="rowgroupcount">矩阵表所有行组个数</param>
        /// <param name="Columns">矩阵表的列组</param>
        /// <param name="CalSumValue">是否在最后加总计</param>
        public static void TableAddRowSubTotal_Matric(DataTable SourceDT, string[] rowgroup_addsubtotaol, int rowgroupcount, string[] Columns, bool CalSumValue)
        {
            #region 计算矩阵化后自动生成的列
            string[] values = new string[SourceDT.Columns.Count - rowgroupcount];
            for (int i = 0; i < SourceDT.Columns.Count - rowgroupcount; i++)
            {
                values[i] = SourceDT.Columns[i + rowgroupcount].ColumnName;
            }
            #endregion

            #region 执行行小计方法
            TableAddRowSubTotal(SourceDT, rowgroup_addsubtotaol, values, CalSumValue);
            #endregion

        }

        public static void TableAddRowSubTotal_Matric(DataTable SourceDT, string[] rowgroup_addsubtotaol, string[] Columns, bool CalSumValue)
        {
            #region 计算矩阵化后自动生成的列
            string[] values = new string[SourceDT.Columns.Count - rowgroup_addsubtotaol.Length];
            for (int i = 0; i < SourceDT.Columns.Count - rowgroup_addsubtotaol.Length; i++)
            {
                values[i] = SourceDT.Columns[i + rowgroup_addsubtotaol.Length].ColumnName;
            }
            #endregion

            #region 执行行小计方法
            TableAddRowSubTotal(SourceDT, rowgroup_addsubtotaol, values, CalSumValue);
            #endregion

        }

        /// <summary>
        /// 给表加总计行
        /// </summary>
        /// <param name="SourceDT"></param>
        /// <param name="NameColumne">放置文本"总计"的列名</param>
        /// <param name="Values">计算总计的列数组</param>
        public static void TableAddSummaryRow(DataTable SourceDT, string NameColumne, string[] Values)
        {
            Hashtable _ht = new Hashtable();

            CalSum(SourceDT, Values, ref _ht);
            AddSumRow(ref SourceDT, new string[1] { NameColumne }, Values, _ht);
        }
        #endregion


        #region 列小计相关
        /// <summary>
        /// 对指定列做小计
        /// </summary>
        /// <param name="SourceTable">要进行小计的数据表</param>
        /// <param name="indexgroup">在矩阵化中列组的索引</param>
        /// <returns>返回计算后的表格</returns>
        public static DataTable ColumnSummaryTotal(DataTable SourceTable, int[] indexgroup, string[] valuegroup)
        {
            DataTable dt = SourceTable.Copy();
            foreach (int index in indexgroup)
            {
                if (index == 0)
                    continue;
                ArrayList al_colname = new ArrayList();
                string parentindexname = "";
                foreach (DataColumn dc in SourceTable.Columns)
                {

                    if (!dc.ColumnName.Contains("→") || dc.ColumnName.Contains("合计→"))
                        continue;
                    if (parentindexname == "")
                    {
                        parentindexname = dc.ColumnName.Split(new char[] { '→' })[index - 1];
                        al_colname.Add(dc.ColumnName);
                    }
                    else
                    {
                        if (parentindexname == dc.ColumnName.Split(new char[] { '→' })[index - 1])
                        {
                            al_colname.Add(dc.ColumnName);
                        }
                        else
                        {
                            InsertColumn(dt, al_colname, index, valuegroup);
                            parentindexname = dc.ColumnName.Split(new char[] { '→' })[index - 1];
                            al_colname.Clear();
                            al_colname.Add(dc.ColumnName);
                        }
                    }
                }
                InsertColumn(dt, al_colname, index, valuegroup);
            }
            return dt;
        }
        /// <summary>
        /// 在指定的位置插入列小计
        /// </summary>
        private static void InsertColumn(DataTable dt, ArrayList al_colname, int index, string[] valuegroup)
        {
            if (valuegroup.Length < 2)
            {
                string addcolumnname = "";
                string[] colname = al_colname[0].ToString().Split(new char[] { '→' });
                #region 获取小计列名
                for (int j = 0; j < colname.Length; j++)
                {
                    if (j < index)
                        addcolumnname += colname[j] + "→";
                    else if (j == index)
                        addcolumnname += "小计→";
                    else
                        addcolumnname += "→";
                }

                addcolumnname = addcolumnname.Substring(0, addcolumnname.Length - 1);
                DataColumn addcolumn = new DataColumn(addcolumnname, typeof(string));
                #endregion

                dt.Columns.Add(addcolumn);

                #region 求插入列的位置
                int position = dt.Columns[al_colname[al_colname.Count - 1].ToString()].Ordinal;
                addcolumn.SetOrdinal(position + 1);
                #endregion

                #region 求小计值
                foreach (DataRow dr in dt.Rows)
                {
                    decimal totalvalue = 0;
                    for (int i = 0; i < al_colname.Count; i++)
                    {
                        totalvalue += decimal.Parse(dr[al_colname[i].ToString()].ToString());
                    }
                    dr[addcolumnname] = totalvalue.ToString();
                }
                #endregion
            }
            else
            {

                for (int i = valuegroup.Length - 1; i >= 0; i--)
                {
                    string addcolumnname = "";
                    string[] colname = al_colname[0].ToString().Split(new char[] { '→' });
                    #region 获取小计列名
                    for (int j = 0; j < colname.Length; j++)
                    {
                        if (j < index)
                            addcolumnname += colname[j] + "→";
                        else if (j == index)
                            addcolumnname += "小计→";
                        else if (j == colname.Length - 1)
                            addcolumnname += valuegroup[i] + "→";
                        else
                            addcolumnname += "→";
                    }
                    addcolumnname = addcolumnname.Substring(0, addcolumnname.Length - 1);
                    DataColumn addcolumn = new DataColumn(addcolumnname, typeof(string));
                    #endregion

                    dt.Columns.Add(addcolumn);

                    #region 求插入列的位置
                    int position = dt.Columns[al_colname[al_colname.Count - 1].ToString()].Ordinal;
                    addcolumn.SetOrdinal(position + 1);
                    #endregion

                    #region 求小计值
                    foreach (DataRow dr in dt.Rows)
                    {
                        decimal totalvalue = 0;
                        for (int k = 0; k < al_colname.Count; k++)
                        {
                            string[] _s = al_colname[k].ToString().Split(new char[] { '→' });
                            if (_s[_s.Length - 1] == valuegroup[i])
                            {
                                totalvalue += decimal.Parse(dr[al_colname[k].ToString()].ToString());
                            }
                        }
                        dr[addcolumnname] = totalvalue.ToString();
                    }
                    #endregion

                }
            }
        }
        #endregion
    }
}
